package net.wanho.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.RequiredArgsConstructor;
import net.wanho.constant.AuthConstant;
import net.wanho.constant.LoginConstant;
import net.wanho.dto.UserLoginDTO;
import net.wanho.entity.UserInfo;
import net.wanho.exception.LoginErrorException;
import net.wanho.mapper.UserInfoMapper;
import net.wanho.service.LoginService;
import net.wanho.util.JwtUtil;
import net.wanho.util.ThreadUtil;
import net.wanho.vo.CaptchaVo;
import net.wanho.vo.CurrUserVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {
    private final StringRedisTemplate stringRedisTemplate;
    private final RedisTemplate<String, Object> redisTemplate;
    private final UserInfoMapper userInfoMapper;

    /**
     * 创建验证码
     * @return CaptchaVo
     */
    @Override
    public CaptchaVo createCaptchaVo() {
        String uuid = UUID.randomUUID().toString();
        String captchaKey = LoginConstant.CAPTCHA_PREFIX + uuid;

        Captcha captcha = new SpecCaptcha();
        String text = captcha.text().toLowerCase();
        String img = captcha.toBase64();

        stringRedisTemplate.opsForValue().set(captchaKey, text, LoginConstant.CAPTCHA_EXPIRE, TimeUnit.MINUTES);

        return new CaptchaVo(uuid, img);
    }

    /**
     * 验证验登录
     * @param userLoginDTO
     * @return Token
     */
    @Override
    public String captchaLogin(UserLoginDTO userLoginDTO) {
        String text = stringRedisTemplate.opsForValue().get(LoginConstant.CAPTCHA_PREFIX + userLoginDTO.getUuid());
        if(Objects.isNull(text)) {
            throw new LoginErrorException("验证码已过期！");
        }
        if(!userLoginDTO.getCode().toLowerCase().equals(text)) {
            throw new LoginErrorException("验证码错误！");
        }

        UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("user_code", userLoginDTO.getUserCode()));
        if(Objects.isNull(userInfo)) {
            throw new LoginErrorException("用户不存在！");
        }

        String userPwd = MD5.create().digestHex(userLoginDTO.getUserPwd());
        if(!userPwd.equals(userInfo.getUserPwd())) {
            throw new LoginErrorException("密码错误！");
        }

        /*Object authInfo = redisTemplate.opsForValue().get(AuthConstant.AUTH_PREFIX + userInfo.getUserId());

        if(Objects.nonNull(authInfo)) {
            throw new LoginErrorException("用户已登录！");
        }*/

        // 生成token
        Map<String, Object> payload = new HashMap<>();
        payload.put(UserInfo.Fields.userId, userInfo.getUserId());
        String token = JwtUtil.generate(payload);

        return LoginConstant.TOKEN_PREFIX + token;
    }

    @Override
    public CurrUserVo getCurrUser() {
        Integer userId = ThreadUtil.getUserId();
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if(Objects.nonNull(userInfo)) {
            CurrUserVo currUserVo = new CurrUserVo();
            currUserVo.setUserId(userInfo.getUserId());

            BeanUtil.copyProperties(userInfo, currUserVo);
            return currUserVo;
        }
        throw new LoginErrorException("获取当前用户失败！");
    }

    /**
     * 登出
     */
    @Override
    public void logout() {
        // 删除redis中用户信息
        redisTemplate.delete(AuthConstant.AUTH_PREFIX + ThreadUtil.getUserId());
    }
}
